import { Vector2 } from './Vector2';
import { BaseCollider } from './BaseCollider';
import {
    Collider,
    ColliderType,
    RectangleColliderOptions,
    CollisionResult
} from './types';

/**
 * 矩形碰撞体类
 */
export class RectangleCollider extends BaseCollider {
    private width: number;
    private height: number;
    private halfWidth: number;
    private halfHeight: number;
    
    constructor(options: RectangleColliderOptions) {
        super(options);
        
        this.width = options.width;
        this.height = options.height;
        this.halfWidth = this.width / 2;
        this.halfHeight = this.height / 2;
        
        this.updateBounds();
    }
    
    /**
     * 检查是否与另一个碰撞体相交
     */
    public intersects(other: Collider): boolean {
        if (!this.canCollideWith(other)) {
            return false;
        }
        
        switch (other.type) {
            case ColliderType.RECTANGLE:
                return this.intersectsRectangle(other as RectangleCollider);
            case ColliderType.CIRCLE:
                return this.intersectsCircle(other);
            case ColliderType.POLYGON:
                return this.intersectsPolygon(other);
            default:
                return false;
        }
    }
    
    /**
     * 检查点是否在碰撞体内
     */
    public contains(point: Vector2): boolean {
        const local = this.worldToLocal(point);
        return Math.abs(local.x) <= this.halfWidth && Math.abs(local.y) <= this.halfHeight;
    }
    
    /**
     * 获取碰撞体中心点
     */
    public getCenter(): Vector2 {
        return this.position.clone().add(this.offset);
    }
    
    /**
     * 获取碰撞体面积
     */
    public getArea(): number {
        return this.width * this.height * this.scale.x * this.scale.y;
    }
    
    /**
     * 克隆碰撞体
     */
    public clone(): RectangleCollider {
        return new RectangleCollider({
            type: ColliderType.RECTANGLE,
            width: this.width,
            height: this.height,
            isTrigger: this.isTrigger,
            tag: this.tag,
            layer: this.layer,
            offset: this.offset.clone(),
            rotation: this.rotation,
            scale: this.scale.clone(),
            enabled: this.enabled
        });
    }
    
    /**
     * 更新碰撞体边界
     */
    protected updateBounds(): void {
        const center = this.getCenter();
        const rotatedHalfWidth = this.halfWidth * this.scale.x;
        const rotatedHalfHeight = this.halfHeight * this.scale.y;
        
        // 计算旋转后的半宽和半高
        const cos = Math.cos(this.rotation);
        const sin = Math.sin(this.rotation);
        const rotatedWidth = Math.abs(rotatedHalfWidth * cos) + Math.abs(rotatedHalfHeight * sin);
        const rotatedHeight = Math.abs(rotatedHalfWidth * sin) + Math.abs(rotatedHalfHeight * cos);
        
        this.bounds.min = center.clone().subtract(new Vector2(rotatedWidth, rotatedHeight));
        this.bounds.max = center.clone().add(new Vector2(rotatedWidth, rotatedHeight));
    }
    
    /**
     * 计算两个碰撞体之间的碰撞结果
     */
    protected calculateCollision(other: Collider): CollisionResult {
        switch (other.type) {
            case ColliderType.RECTANGLE:
                return this.calculateRectangleCollision(other as RectangleCollider);
            case ColliderType.CIRCLE:
                return this.calculateCircleCollision(other);
            case ColliderType.POLYGON:
                return this.calculatePolygonCollision(other);
            default:
                return { collided: false };
        }
    }
    
    /**
     * 检查是否与矩形碰撞体相交
     */
    private intersectsRectangle(other: RectangleCollider): boolean {
        const result = this.calculateRectangleCollision(other);
        return result.collided;
    }
    
    /**
     * 检查是否与圆形碰撞体相交
     */
    private intersectsCircle(other: Collider): boolean {
        const result = this.calculateCircleCollision(other);
        return result.collided;
    }
    
    /**
     * 检查是否与多边形碰撞体相交
     */
    private intersectsPolygon(other: Collider): boolean {
        const result = this.calculatePolygonCollision(other);
        return result.collided;
    }
    
    /**
     * 计算与矩形碰撞体的碰撞结果
     */
    private calculateRectangleCollision(other: RectangleCollider): CollisionResult {
        // 获取两个矩形的中心点
        const centerA = this.getCenter();
        const centerB = other.getCenter();
        
        // 计算两个矩形在x和y轴上的投影重叠
        const overlapX = Math.abs(centerA.x - centerB.x) - (this.halfWidth * this.scale.x + other.halfWidth * other.scale.x);
        const overlapY = Math.abs(centerA.y - centerB.y) - (this.halfHeight * this.scale.y + other.halfHeight * other.scale.y);
        
        // 如果没有重叠，则没有碰撞
        if (overlapX >= 0 || overlapY >= 0) {
            return { collided: false };
        }
        
        // 计算碰撞法线和穿透深度
        let normal: Vector2;
        let penetration: number;
        
        if (overlapX > overlapY) {
            normal = new Vector2(centerA.x < centerB.x ? -1 : 1, 0);
            penetration = -overlapX;
        } else {
            normal = new Vector2(0, centerA.y < centerB.y ? -1 : 1);
            penetration = -overlapY;
        }
        
        // 计算碰撞点（取两个矩形重叠区域的中心点）
        const contactPoint = new Vector2(
            (Math.min(this.bounds.max.x, other.bounds.max.x) + Math.max(this.bounds.min.x, other.bounds.min.x)) / 2,
            (Math.min(this.bounds.max.y, other.bounds.max.y) + Math.max(this.bounds.min.y, other.bounds.min.y)) / 2
        );
        
        return {
            collided: true,
            contactPoint,
            normal,
            penetration
        };
    }
    
    /**
     * 计算与圆形碰撞体的碰撞结果
     */
    private calculateCircleCollision(other: Collider): CollisionResult {
        // 获取矩形的中心点和圆形的中心点
        const rectCenter = this.getCenter();
        const circleCenter = other.getCenter();
        
        // 将圆形中心点转换到矩形的局部坐标系
        const localCircle = this.worldToLocal(circleCenter);
        
        // 找到矩形上距离圆形中心最近的点
        const closest = new Vector2(
            Math.max(-this.halfWidth, Math.min(this.halfWidth, localCircle.x)),
            Math.max(-this.halfHeight, Math.min(this.halfHeight, localCircle.y))
        );
        
        // 计算圆形中心到最近点的距离
        const distance = closest.distance(localCircle);
        const radius = (other as any).radius * other.scale.x; // 假设圆形碰撞体有radius属性
        
        // 如果没有重叠，则没有碰撞
        if (distance > radius) {
            return { collided: false };
        }
        
        // 计算碰撞法线和穿透深度
        const normal = this.localToWorld(closest).subtract(circleCenter).normalized;
        const penetration = radius - distance;
        
        // 计算碰撞点
        const contactPoint = circleCenter.clone().add(normal.clone().multiply(radius));
        
        return {
            collided: true,
            contactPoint,
            normal,
            penetration
        };
    }
    
    /**
     * 计算与多边形碰撞体的碰撞结果
     */
    private calculatePolygonCollision(other: Collider): CollisionResult {
        // 获取多边形的顶点
        const vertices = (other as any).vertices.map((v: Vector2) => {
            const worldPos = new Vector2();
            // 假设多边形碰撞体有类似的方法
            if (typeof (other as any).localToWorld === 'function') {
                return (other as any).localToWorld(v);
            }
            return worldPos;
        });
        
        // 检查多边形的顶点是否与矩形相交
        for (const vertex of vertices) {
            if (this.contains(vertex)) {
                return {
                    collided: true,
                    contactPoint: vertex.clone(),
                    normal: this.getCenter().subtract(vertex).normalized,
                    penetration: 0 // 需要更精确的计算
                };
            }
        }
        
        // 检查矩形的顶点是否与多边形相交
        const rectVertices = [
            this.localToWorld(new Vector2(-this.halfWidth, -this.halfHeight)),
            this.localToWorld(new Vector2(this.halfWidth, -this.halfHeight)),
            this.localToWorld(new Vector2(this.halfWidth, this.halfHeight)),
            this.localToWorld(new Vector2(-this.halfWidth, this.halfHeight))
        ];
        
        for (const vertex of rectVertices) {
            if ((other as any).contains(vertex)) {
                return {
                    collided: true,
                    contactPoint: vertex.clone(),
                    normal: other.getCenter().subtract(vertex).normalized,
                    penetration: 0 // 需要更精确的计算
                };
            }
        }
        
        // 检查边与边的相交
        // 这里需要实现更复杂的边相交检测算法
        // 可以使用分离轴定理（SAT）或GJK算法
        
        return { collided: false };
    }
} 